package com.kwan.xframe.pay.wx;

import android.app.Activity;
import android.util.Log;
import android.util.Xml;

import com.kwan.xframe.api.BaseAPIUtil;
import com.kwan.xframe.api.DataSubscriber;
import com.kwan.xframe.api.DataSubscriberListener;
import com.kwan.xframe.common.bean.BaseNameValuePair;
import com.kwan.xframe.pay.EasyPay;
import com.kwan.xframe.pay.PayParams;
import com.kwan.xframe.pay.PayWay;
import com.kwan.xframe.pay.PrePayInfo;
import com.kwan.xframe.pay.callback.OnPayResultListener;

import org.xmlpull.v1.XmlPullParser;

import java.io.StringReader;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;

import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import retrofit2.http.Body;
import retrofit2.http.POST;

public class WXPayUtil extends BaseAPIUtil {


	private String payKey;
	private Activity activity;

	public WXPayUtil(String payKey, Activity activity) {
		this.payKey = payKey;
		this.activity = activity;
		// 统一下单
//		String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
//		WXPrePost post = new WXPrePost();
//		post.appid = "你的APP_ID";
//		post.mch_id = "你的商户号";
//		post.nonce_str = genNonceStr();//随机字符串  **1
//		post.body = "介绍";
//		post.detail = "打赏";
//		post.out_trade_no = getTradeNo(); //商户订单号 **2
//		post.total_fee = 1;//单位是分
//		post.spbill_create_ip = getLocalIpAddress();//ip地址  **3
//		post.notify_url = "http://www.weixin.qq.com/wxpay/pay.php";//这里是后台接受支付结果通知的url地址
//		post.trade_type = "APP";
//		post.sign = genPackageSign(post);//签名  **4

	}


	public void prePay(final WXPrePost post, final OnPayResultListener listener) {
		String xmlBody = toXml(getFirstSignParams(post));
		Log.e("kwan", "xml:" + xmlBody);

		Disposable disposable = serverAPI(TYPE_XML).create(API.class).getPrePayString(xmlBody)
				.subscribeOn(Schedulers.io())
				.observeOn(Schedulers.io())
				.subscribeWith(new DataSubscriber<>(new DataSubscriberListener<Object>() {
					@Override
					public void onDataCompleted(int vocational_id, HashMap<String, Object> exData) {

					}

					@Override
					public void onDataError(int vocational_id, HashMap<String, Object> exData, Throwable throwable) {

					}

					@Override
					public void onDataNext(int vocational_id, HashMap<String, Object> exData, Object data) {
						Log.e("kwan", "xml:" + data);
						Map<String, String> stringMap = decodeXml((String) data);
						if (stringMap.get("return_code").equals("SUCCESS") && stringMap.get("result_code").equals("SUCCESS")) {
							pay(stringMap, post, listener);
						}
					}
				}));
	}

	public void pay(Map<String, String> stringMap, WXPrePost wxPrePost, OnPayResultListener onPayResultListener) {

		PrePayInfo prePayInfo = new PrePayInfo();
		prePayInfo.appid = wxPrePost.appid; //stringMap.get("appid");
		prePayInfo.prepayid = stringMap.get("prepay_id");
		prePayInfo.partnerid = wxPrePost.mch_id;//stringMap.get("mch_id");
		prePayInfo.noncestr = stringMap.get("nonce_str");
		prePayInfo.packageValue = "Sign=WXPay";
		prePayInfo.timestamp = String.valueOf(System.currentTimeMillis() / 1000);
		prePayInfo.sign = genSecondPackageSign(getSecondSignParams(prePayInfo.appid, prePayInfo.prepayid, prePayInfo.partnerid, prePayInfo.noncestr, prePayInfo.timestamp));

		PayParams payParams = new PayParams.Builder(activity)
				.payWay(PayWay.WeChatPay)
				.goodsName(wxPrePost.detail)
				.goodsIntroduction(wxPrePost.detail)
				.goodsPrice(wxPrePost.total_fee)
				.wechatAppID(wxPrePost.appid)
				.build();

		new EasyPay(payParams).toPay(onPayResultListener).doPay(null, prePayInfo);

	}

	public interface API {
		@POST("pay/unifiedorder")
		Flowable<String> getPrePayString(@Body String arg);
		int PRE_PAY_VOCATIONAL_ID = 0x000000;
	}

	private List<BaseNameValuePair> getFirstSignParams(WXPrePost params) {

		List<BaseNameValuePair> packageParams = new LinkedList<>();
		packageParams.add(new BaseNameValuePair("appid", params.appid));
		packageParams.add(new BaseNameValuePair("body", params.body));
		packageParams.add(new BaseNameValuePair("detail", params.detail));
		packageParams.add(new BaseNameValuePair("mch_id", params.mch_id));
		packageParams.add(new BaseNameValuePair("nonce_str", params.nonce_str));
		packageParams.add(new BaseNameValuePair("notify_url", params.notify_url));
		packageParams.add(new BaseNameValuePair("out_trade_no", params.out_trade_no));
		packageParams.add(new BaseNameValuePair("spbill_create_ip", params.spbill_create_ip));
		packageParams.add(new BaseNameValuePair("total_fee", params.total_fee + ""));
		packageParams.add(new BaseNameValuePair("trade_type", params.trade_type));
		packageParams.add(new BaseNameValuePair("sign", params.sign));

		return packageParams;


	}

	public String genNonceStr() {
		Random random = new Random();
		//这里就用到了微信实例代码中的MD5那个类
		return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
	}

	public String getLocalIpAddress() {
		StringBuilder IFCONFIG = new StringBuilder();
		try {
			for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
				NetworkInterface intf = en.nextElement();
				for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
					InetAddress inetAddress = enumIpAddr.nextElement();
					if (!inetAddress.isLoopbackAddress() && !inetAddress.isLinkLocalAddress() && inetAddress.isSiteLocalAddress()) {
						IFCONFIG.append(inetAddress.getHostAddress().toString() + ",");
						break;
					}

				}
			}
			String[] split = IFCONFIG.toString().split(",");
			if (split != null && split.length > 0) {
				String ip = split[0];
				if (ip != null && ip.length() > 0) {
					return ip;
				} else {
					return "127.0.0.1";
				}
			} else {
				return "127.0.0.1";
			}
		} catch (SocketException ex) {
			return "127.0.0.1";

		}
	}

	private String toXml(List<BaseNameValuePair> params) {
		StringBuilder sb = new StringBuilder();
		sb.append("<xml>");
		for (int i = 0; i < params.size(); i++) {
			sb.append("<" + params.get(i).getName() + ">");
			sb.append(params.get(i).getValue());
			sb.append("</" + params.get(i).getName() + ">");
		}
		sb.append("</xml>");
		return sb.toString();
	}

	public Map<String, String> decodeXml(String content) {

		try {
			Map<String, String> xml = new HashMap<>();
			XmlPullParser parser = Xml.newPullParser();
			parser.setInput(new StringReader(content));
			int event = parser.getEventType();
			while (event != XmlPullParser.END_DOCUMENT) {
				String nodeName = parser.getName();
				switch (event) {
					case XmlPullParser.START_DOCUMENT:
						break;
					case XmlPullParser.START_TAG:
						if (!"xml".equals(nodeName)) {
							xml.put(nodeName, parser.nextText());
						}
						break;
					case XmlPullParser.END_TAG:
						break;
				}
				event = parser.next();
			}
			return xml;
		} catch (Exception e) {
		}
		return null;
	}


	/**
	 * 生成签名
	 *
	 * @param params
	 */
	public String genPackageSign(WXPrePost params) {
		//拼接排序list
		List<BaseNameValuePair> packageParams = new LinkedList<>();
		packageParams.add(new BaseNameValuePair("appid", params.appid));
		packageParams.add(new BaseNameValuePair("body", params.body));
		packageParams.add(new BaseNameValuePair("detail", params.detail));
		packageParams.add(new BaseNameValuePair("mch_id", params.mch_id));
		packageParams.add(new BaseNameValuePair("nonce_str", params.nonce_str));
		packageParams.add(new BaseNameValuePair("notify_url", params.notify_url));
		packageParams.add(new BaseNameValuePair("out_trade_no", params.out_trade_no));
		packageParams.add(new BaseNameValuePair("spbill_create_ip", params.spbill_create_ip));
		packageParams.add(new BaseNameValuePair("total_fee", params.total_fee + ""));
		packageParams.add(new BaseNameValuePair("trade_type", params.trade_type));
		StringBuilder sb = new StringBuilder();

		for (int i = 0; i < packageParams.size(); i++) {
			sb.append(packageParams.get(i).getName());
			sb.append('=');
			sb.append(packageParams.get(i).getValue());
			sb.append('&');
		}
		sb.append("key=");
		sb.append(payKey);
		//key设置路径：微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置
		//这里又用到了从实例代码复制的MD5 可以去上面copy
		String packageSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
		return packageSign;
	}


	//获取参数列表
	private List<BaseNameValuePair> getSecondSignParams(String appId, String prepayId, String partnerid, String nonceStr, String timeStamp) {
		//appId，partnerId，prepayId，nonceStr，timeStamp，package
		List<BaseNameValuePair> packageParams = new LinkedList<>();
		packageParams.add(new BaseNameValuePair("appid", appId));
		packageParams.add(new BaseNameValuePair("noncestr", nonceStr));
		packageParams.add(new BaseNameValuePair("package", "Sign=WXPay"));
		packageParams.add(new BaseNameValuePair("partnerid", partnerid));
		packageParams.add(new BaseNameValuePair("prepayid", prepayId));
		packageParams.add(new BaseNameValuePair("timestamp", timeStamp));
		return packageParams;
	}

	//第二次签名
	private String genSecondPackageSign(List<BaseNameValuePair> params) {
		//拼接排序list
		StringBuilder sb = new StringBuilder();

		for (int i = 0; i < params.size(); i++) {
			sb.append(params.get(i).getName());
			sb.append('=');
			sb.append(params.get(i).getValue());
			sb.append('&');
		}
		sb.append("key=");
		sb.append(payKey);//上面已经获取
		String packageSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
		return packageSign;
	}

	@Override
	protected String getBaseUrl() {
		return "https://api.mch.weixin.qq.com/";
	}

	@Override
	protected String getBaseTokenUrl() {
		return null;
	}

	@Override
	protected String getBaseUpLoadUrl() {
		return null;
	}

	@Override
	protected String getToken() {
		return null;
	}
}
